package pkg60311assign3;

import java.util.Calendar;
import java.io.File;
import java.io.FileWriter;
import java.io.FileReader;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.regex.Pattern;

public class userProfiler {

    // First and last name must not be empty, null or contain numbers.
    public static Boolean isValidName(String name) {
        try {
            String regex = "[A-Za-z]+";
            return Pattern.matches(regex, name);
        } catch (Exception e) {
            System.err.println("[isValidName] " + e.getMessage());
            return false;
        }
    }

    // Middle name must not be empty or contain numbers, but can be null.
    public static Boolean isValidMiddleName(String name) {
        try {
            String regex = "[A-Za-z]+";
            return Pattern.matches(regex, name);
        } catch (NullPointerException e) {
            return true;
        } catch (Exception e) {
            System.err.println("[isValidMiddleName] " + e.getMessage());
            return false;
        }
    }

    // Converts from imperial to metric.
    public static double convertHeightToCm(Integer heightFeet, Integer heightInches) {
        try {
            return (heightFeet * 12 + heightInches) * 2.54;
        } catch (NullPointerException npe) {
            try {
                return heightFeet * 12 * 2.54;
            } catch (NullPointerException npe2) {
                try {
                    return heightInches * 2.54;
                } catch (NullPointerException npe3) {
                    System.err.println("[convertHeightToCm] Both values null.\n\t=> " + npe.getMessage());
                    return 0;
                }
            }
        } catch (Exception e) {
            System.err.println("[convertHeightToCm] " + e.getMessage());
            return 0;
        }
    }

    // Height must be between 57 and 272 cm (shortest and tallest adult heights on record)
    public static Boolean isValidHeight(double height) {
        try {
            if (height > 57 && height < 272) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            System.err.println("[isValidHeight] " + e.getMessage());
            return false;
        }
    }

    // Converts from imperial to metric.
    public static double convertWeightToKg(Double weight) {
        try {
            return weight / 2.20462262185;
        } catch (Exception e) {
            System.err.println("[convertWeightToKg] " + e.getMessage());
            return 0;
        }
    }

    // Weight must be between 2 and 636 kg (lightest and heaviest adults weights on record)
    public static Boolean isValidWeight(double weight) {
        try {
            if (weight > 2 && weight < 636) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            System.err.println("[isValidWeight] " + e.getMessage());
            return false;
        }
    }

    // Check that the data used to populate the Calendar object is valid
    public static Boolean isValidDate(String date) {

            if (date == null){
                return false;
            }

            //set the format to use as a constructor argument
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

            if (date.trim().length() != dateFormat.toPattern().length()){
                return false;
        }
            
            dateFormat.setLenient(false);

        try {
            //parse the date parameter
            dateFormat.parse(date.trim());
        }
        catch (Exception pe) {
            return false;
        }
            return true;
    }


    

    // Age must be between 18 and 123 years old (age of majority and oldest person on record)
    public static Boolean isValidBirthdate(Calendar birthdate) {
        try {
            Calendar cNow = Calendar.getInstance();
            Calendar cMin = Calendar.getInstance();
            Calendar cMax = Calendar.getInstance();

            cMin.set(Calendar.YEAR, cNow.get(Calendar.YEAR) - 18);
            cMax.set(Calendar.YEAR, cNow.get(Calendar.YEAR) - 123);

            if (birthdate.before(cMin) && birthdate.after(cMax)) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            System.err.println("[isValidBirthdate] " + e.getMessage());
            return false;
        }
    }

    // Returns a globally unique identifier.  This throws an IOException if the number of GUIDs for the year is reached and will not write more than '9999' to guid.bin
    public static String createGUID() throws IOException {
        Calendar cNow = Calendar.getInstance();

        try {
            File ioFile = new File("./guid.bin");

            // if guid.bin doesn't exist, create it and write '0' to it.
            if (!ioFile.exists()) {
                try {
                    ioFile.createNewFile();
                    FileWriter out = new FileWriter(ioFile);
                    String outString = new String();
                    outString += cNow.get(Calendar.YEAR) + ".0000";

                    out.write(outString.toCharArray());
                    out.flush();
                    out.close();

                } catch (Exception e) {
                    System.err.println("[createGUID] Error creating guid.bin\n" + e.getMessage());
                    FileWriter out = new FileWriter(ioFile);
                    out.close();
                    return "Could not create GUID";
                }
            }

            FileReader in = new FileReader(ioFile);
            char[] buf = new char[9];
            int chs = in.read(buf);
            in.close();

            if (chs > 0) {
                char[] yr = new char[4];
                char[] num = new char[4];
                String idString = new String(buf);
                idString.getChars(0, 4, yr, 0);
                idString.getChars(5, 9, num, 0);
                String numString = new String(num);
                String yrString = new String(yr);
                Integer year = Integer.parseInt(yrString.trim());

                Integer id = 0;

                // If a new year has started, restart the IDs
                if (year == cNow.get(Calendar.YEAR)) {
                    id = Integer.parseInt(numString.trim());
                }

                ++id;

                if (id < 10) {
                    idString = "" + cNow.get(Calendar.YEAR) + ".000" + id;
                } else if (id < 100) {
                    idString = "" + cNow.get(Calendar.YEAR) + ".00" + id;
                } else if (id < 1000) {
                    idString = "" + cNow.get(Calendar.YEAR) + ".0" + id;
                } else {
                    idString = "" + cNow.get(Calendar.YEAR) + "." + id;
                }

                try {
                    // Check that GUIDs are available
                    if (id < 10000) {
                        FileWriter out = new FileWriter(ioFile);
                        out.write(idString.toCharArray());
                        out.flush();
                        out.close();
                    } else {
                        FileWriter out = new FileWriter(ioFile);
                        out.close();

                        throw new IOException("Out of GUIDs for this year.");
                    }
                    return idString;
                } catch (Exception e) {
                    FileWriter out = new FileWriter(ioFile);
                    out.close();

                    System.err.println("[createGUID] Error writing to guid.bin\n\t=> " + e.getMessage());
                    throw e;
                }
            } else {
                System.err.println("[createGUID] Could not read from guid.bin");
                return "Could not create GUID";
            }

        } catch (NumberFormatException nfe) {
            FileReader in = new FileReader(new File("./guid.bin"));
            in.close();

            System.err.println("[createGUID] guid.bin has been corrupted.  A function would be called here which would take a GUID value as input to rebuild guid.bin.");
            return "Could not create GUID";

        } catch (Exception e) {
            FileReader in = new FileReader(new File("./guid.bin"));
            in.close();

            System.err.println("[createGUID] Could not create a GUID.\n\t=> " + e.getMessage());
            return "Could not create GUID";
        }
    }


}
